/*-------------------------------- Arctic Core ------------------------------
 * Copyright (C) 2013, ArcCore AB, Sweden, www.arccore.com.
 * Contact: <contact@arccore.com>
 *
 * You may ONLY use this file:
 * 1)if you have a valid commercial ArcCore license and then in accordance with
 * the terms contained in the written license agreement between you and ArcCore,
 * or alternatively
 * 2)if you follow the terms found in GNU General Public License version 2 as
 * published by the Free Software Foundation and appearing in the file
 * LICENSE.GPL included in the packaging of this file or here
 * <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>
 *-------------------------------- Arctic Core -----------------------------*/


#ifndef CANNM_INTERNAL_H_
#define CANNM_INTERNAL_H_

#include <stdbool.h>
#include "CanNm_Types.h"


/** Operational modes of the network management */
typedef enum {
	NM_MODE_BUS_SLEEP,
	NM_MODE_PREPARE_BUS_SLEEP,
	NM_MODE_SYNCHRONIZE,
	NM_MODE_NETWORK
} Nm_ModeType;

/** States of the network management state machine */
typedef enum {
	NM_STATE_UNINIT,
	NM_STATE_BUS_SLEEP,
	NM_STATE_PREPARE_BUS_SLEEP,
	NM_STATE_READY_SLEEP,
	NM_STATE_NORMAL_OPERATION,
	NM_STATE_REPEAT_MESSAGE,
	NM_STATE_SYNCHRONIZE
} Nm_StateType;

typedef enum {
	CANNM_UNINIT,
	CANNM_INIT
} CanNm_InitStatusType;

typedef struct {
	Nm_ModeType				Mode;
	Nm_StateType			State;
	bool					Requested;
	uint32_t				TimeoutTimeLeft;				/* T[T_NM_TIMEOUT = 2000ms] */
	uint32_t				RepeatMessageTimeLeft;			/* T[T_REPEAT_MESSAGE = 1500ms] */
	uint32_t				WaitBusSleepTimeLeft;			/* T[T_WAIT_BUS_SLEEP = 2000ms] */
	uint32_t				WaitBusSleepWakeUpTimeLeft;		/* T[T_WakeUp] HHT=100ms JJset = 50ms*/
	uint32_t				MessageCycleTimeLeft;			/* T[T_NM_MessageCycle = 500ms] */
	uint32_t				MessageCycleOffsetTimeLeft;		/* MessageCycleOffsetTime = 0 */
	uint32_t				MessageTimeoutTimeLeft;			/* T[Tx-Timeout] 2000 */
	uint8_t					TxMessageSdu[8];
	uint8_t					RxMessageSdu[8];
	uint8_t					immediateNmTransmissionsSent;	/* 5 */
	bool					immediateModeActive;
	bool 	                CommunicationEnabled;
	uint32_t				PudMessageCycleTimeLeft;		/* APP PDU */
} CanNm_Internal_ChannelType;

typedef struct {
	CanNm_InitStatusType 		InitStatus;
	CanNm_Internal_ChannelType	Channels;
} CanNm_InternalType;


/* Timer helpers */
static inline void CanNm_Internal_TickTimeoutTime( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_TickRepeatMessageTime( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_TickWaitBusSleepTime( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_TickWaitBusSleepWakeUpTime( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_TickMessageCycleTime( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_TickTxTimeout(const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_ClearCbv( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );

/* Message helpers */
static inline void CanNm_Internal_TransmitMessage( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline uint8_t CanNm_Internal_GetUserDataOffset( const CanNm_ConfigType* ChannelConf );
static inline uint8_t* CanNm_Internal_GetUserDataPtr( const CanNm_ConfigType* ChannelConf, uint8_t* MessageSduPtr );
static inline uint8_t CanNm_Internal_GetUserDataLength( const CanNm_ConfigType* ChannelConf );

/* Transition helpers */
static inline void CanNm_Internal_PrepareBusSleep_to_RepeatMessage( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ,bool isNwReq );
static inline void CanNm_Internal_PrepareBusSleep_to_BusSleep( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );

static inline void CanNm_Internal_BusSleep_to_RepeatMessage( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal, bool isNwReq );
static inline void CanNm_Internal_BusSleep_to_BusSleep( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );

static inline void CanNm_Internal_RepeatMessage_to_RepeatMessage( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_RepeatMessage_to_ReadySleep( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_RepeatMessage_to_NormalOperation( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );

static inline void CanNm_Internal_NormalOperation_to_RepeatMessage( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_NormalOperation_to_ReadySleep( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_NormalOperation_to_NormalOperation( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );

static inline void CanNm_Internal_ReadySleep_to_NormalOperation( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_ReadySleep_to_PrepareBusSleep( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );
static inline void CanNm_Internal_ReadySleep_to_RepeatMessage( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );

static inline void CanNm_Internal_NetworkMode_to_NetworkMode( const CanNm_ConfigType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal );


#endif /* CANNM_INTERNAL_H_ */


